/**
 * 
 */
package com.roshan.web.security.handlers;

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;

import com.roshan.web.dto.UpdateExpiredPasswordDetail;
import com.roshan.web.security.cryptography.IRoarCryptographyProvider;
import com.roshan.web.security.domain.RoarAuthenticationToken;
import com.roshan.web.security.domain.RoarMFAAuthenticationToken;
import com.roshan.web.security.service.ICookieService;
import com.roshan.web.security.util.CookieUtils;
import com.roshan.web.service.IUserService;
import com.roshan.web.util.constants.CommonConstants;

@SuppressWarnings("nls")
public class RoarAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    private @Value("${roar.security.cookie.mfa.name}")
    String mfaCookieName;

    private @Value("${roar.security.cookie.name}")
    String securityCookieName;

    private final RequestCache requestCache = new HttpSessionRequestCache();

    @Autowired
    private ICookieService cookieService;

    @Autowired
    private IRoarCryptographyProvider cryptographyProvider;

    @Autowired
    private IUserService userService;

    /** The customer password update url. */
    private String customerPasswordUpdateUrl;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws ServletException, IOException {

        RoarAuthenticationToken roarAuthenticationToken = (RoarAuthenticationToken) authentication;

        SavedRequest savedRequest = this.requestCache.getRequest(request, response);

        String userName = roarAuthenticationToken.getPrincipal().toString();
        String customerUri = roarAuthenticationToken.getUserUri();

        String mfaCookieContent = (String) this.cookieService.retrieveCookiePersistedObject(CookieUtils
                .getMFACookieName(this.mfaCookieName, customerUri), request);

        RoarMFAAuthenticationToken mfaToken = (RoarMFAAuthenticationToken) this.cookieService
                .retrieveCookiePersistedObject(this.mfaCookieName, request);

        if (!this.cookieService.isValidMFACookieContent(mfaCookieContent, userName, customerUri) && mfaToken != null) {
            createMFACookie(request, response, userName, customerUri);
        }

        String encUserUri = this.cryptographyProvider.encrypt(roarAuthenticationToken.getUserUri());
        String encodedUserUri = URLEncoder.encode(encUserUri, CommonConstants.ENCODING_UTF_8);

        if (mfaToken != null) {
            this.cookieService.removeCookie(this.mfaCookieName, request, response);
        }
        if (roarAuthenticationToken.isPasswordExpired()) {
            if (savedRequest != null) {
                this.requestCache.removeRequest(request, response);
            }

            UpdateExpiredPasswordDetail updateExpiredPasswordDetail = this.userService
                    .retrieveUpdateExpiredPasswordRequest(roarAuthenticationToken.getUserUri());

            String encCode = this.cryptographyProvider.encrypt(updateExpiredPasswordDetail.getCode());
            String encodedCode = URLEncoder.encode(encCode, CommonConstants.ENCODING_UTF_8);

            super.setDefaultTargetUrl(this.customerPasswordUpdateUrl + "securityInfo=" + encodedUserUri + "&code="
                    + encodedCode);
        } else {
            if (savedRequest != null) {
                String redirectUrl = savedRequest.getRedirectUrl();
                this.requestCache.removeRequest(request, response);
                super.setDefaultTargetUrl(redirectUrl);
            } else {
                super.setDefaultTargetUrl("/");
            }

            roarAuthenticationToken.setCheckPassword(false);
            roarAuthenticationToken.setCheckMFA(false);

            do {
                this.cookieService.createRoarSecurityContext(roarAuthenticationToken, request, response);
                this.cookieService.createRoarSecurityTimeOutContext(request, response);
            } while (this.cookieService.retrieveCookie(this.securityCookieName, request) != null);
        }
        super.onAuthenticationSuccess(request, response, authentication);
    }

    @Override
    protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {

        return super.determineTargetUrl(request, response);
    }

    /**
     * @param customerPasswordUpdateUrl the customerPasswordUpdateUrl to set
     */
    public void setCustomerPasswordUpdateUrl(String customerPasswordUpdateUrl) {
        this.customerPasswordUpdateUrl = customerPasswordUpdateUrl;
    }

    /**
     * @return the customerPasswordUpdateUrl
     */
    public String getCustomerPasswordUpdateUrl() {
        return this.customerPasswordUpdateUrl;
    }

    private void createMFACookie(HttpServletRequest request, HttpServletResponse response, String userName,
            String customerUri) {

        this.cookieService.createMFASecurityContext(userName, customerUri, request, response);

    }

}
